package com.cm.dynamic.classloader.factory;

import com.cm.dynamic.autoconfigure.Configuration;
import com.cm.dynamic.classloader.ModuleClassLoader;
import com.cm.dynamic.classloader.context.ClassLoaderContext;
import com.cm.dynamic.classloader.context.ClassloaderResponsity;
import com.cm.dynamic.scan.ModuleClassPathScanner;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 默认的类加载工厂
 * @author xionglei
 * @version 1.0.0
 * 2021年08月26日 15:49
 */
public class DefaultClassLoaderFactory implements ClassLoaderFactory {

    private final Configuration configuration;

    public DefaultClassLoaderFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    /**
     * 构建类加载器
     * @return
     */
    @Override
    public ClassLoader buildClassLoader() {

        ModuleClassLoader moduleClassLoader = new ModuleClassLoader();
        try {
            ClassLoaderContext.setCurrentProxy(moduleClassLoader);
            String[] jarLocations = configuration.getJarLocations();
            if (jarLocations != null && jarLocations.length != 0) {
                // 模块名
                String moduleName = jarLocations.toString();
                if(ClassloaderResponsity.getInstance().containsClassLoader(moduleName)){
                    ClassloaderResponsity.getInstance().removeClassLoader(moduleName);
                }
                for (String jarLocation : jarLocations) {
                    // 增加classpath和加载类文件到jvm
                    moduleClassLoader.addUcpLoadClass(jarLocation);
                    // 初始化加载Spring bean
                    initRegisterSpringBean(moduleClassLoader, configuration);
                }
                // 保存此次加载模块和类加载器关系
                ClassloaderResponsity.getInstance().addClassLoader(moduleName, moduleClassLoader);
            }
        } finally {
            ClassLoaderContext.removeClassLoader();
        }
        return moduleClassLoader;
    }

    /**
     * 方法描述 初始化spring bean
     *
     * @method initBean
     */
    private void initRegisterSpringBean(ModuleClassLoader moduleClassLoader, Configuration configuration) {
        String[] basePackages = configuration.getBasePackages();
        if (basePackages != null && basePackages.length != 0) {
            // 扫描注入Spring容器中,并且加载相应mybatis的mapper 和 mapper.xml
            Set<BeanDefinitionHolder> beanDefinitionHolders = ModuleClassPathScanner.getInstance().doScan(configuration);
            // 注册到类加载器中registeredBeanName容器中
            if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
                List<String> beanNames = beanDefinitionHolders.stream().map(BeanDefinitionHolder::getBeanName).collect(Collectors.toList());
                // 添加到累加器记录已加载到Spring容器中的beanName
                moduleClassLoader.getRegisteredBeanName().addAll(beanNames);
            }
        }
    }

    @Override
    public Configuration getConfiguration() {
        return configuration;
    }
}
